﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;


namespace EMguConsole.Core
{
    public class FindCenterPositioning
    {
        public static string path = @"C:\Users\93143\Desktop\2.jpg";

        // 检测的颜色
        public static Bgr ColorCheck = new Bgr(49, 36, 158);
        public static void Find()
        {
            // 读取图像
            Mat imageBase = CvInvoke.Imread(path, ImreadModes.Color);

            // 去除噪声
            Mat image = new Mat();
            CvInvoke.MedianBlur(imageBase, image, 5);

            // 转换图像为灰度
            Mat grayImage = new Mat();
            CvInvoke.CvtColor(image, grayImage, ColorConversion.Bgr2Gray);

            // 使用霍夫变换检测圆
            CircleF[] circles = CvInvoke.HoughCircles(
                grayImage,
                HoughModes.Gradient,
                1.0, // 累加器分辨率
                20.0, // 最小圆的中心距离
                param1: 50, // Canny 边缘检测的高阈值
                param2: 30, // 圆心检测阈值
                minRadius: 10, // 最小圆半径
                maxRadius: 25 // 最大圆半径
            );

            /*
                [DisplayColor(255, 0, 0)]
                public double Blue
                [DisplayColor(0, 255, 0)]
                public double Green
                [DisplayColor(0, 0, 255)]
                public double Red
             */

            circles = circles.OrderBy(e => e.Center.X).ToArray();

            var RediusAdd = 30;
            // 绘制检测到的圆，只绘制红色圆心的圆
            foreach (CircleF circle in circles)
            {
                // 计算圆心附近像素的平均颜色
                Bgr avgColor = CalculateAverageColor(image, (int)circle.Center.X, (int)circle.Center.Y, 5);
                // Console.WriteLine(avgColor.Blue.ToString() + " " + avgColor.Green.ToString() + " " + avgColor.Red.ToString());

                // 判断颜色是否接近于红色（可根据具体颜色范围进行调整）
                if (CalculateColorDifference(avgColor, ColorCheck) < 100)
                {
                    // 绘制圆心
                    //CvInvoke.Circle(image, Point.Round(circle.Center), (int)circle.Radius , new MCvScalar(0, 255, 0), 2);

                    // 绘制外圆
                    CvInvoke.Circle(image, Point.Round(circle.Center), (int)circle.Radius + RediusAdd, new MCvScalar(0, 255, 255), 2);

                    // 绘制十字标志
                    int crossLength = 10; // 十字标志长度
                    Point crossCenter = Point.Round(circle.Center);
                    CvInvoke.Line(image, new Point(crossCenter.X - crossLength, crossCenter.Y), new Point(crossCenter.X + crossLength, crossCenter.Y), new MCvScalar(0, 255, 255), 2);
                    CvInvoke.Line(image, new Point(crossCenter.X, crossCenter.Y - crossLength), new Point(crossCenter.X, crossCenter.Y + crossLength), new MCvScalar(0, 255, 255), 2);


                    #region 第一个圆判断
                    // if (++idx == 4)
                    {
                        // 定义一些圆周上的点
                        int numPoints = 36 ; // 圆周上的点数
                        Point[] points = new Point[numPoints];

                        // 计算圆周上的点
                        for (int i = 0; i < numPoints; i++)
                        {
                            double angle = i * 2 * Math.PI / numPoints;
                            int x = (int)(circle.Center.X + (RediusAdd + circle.Radius)  * Math.Cos(angle));
                            int y = (int)(circle.Center.Y + (RediusAdd + circle.Radius)  * Math.Sin(angle));
                            points[i] = new Point(x, y);

                            // 绘制刻度
                            //CvInvoke.Line(image, points[i], points[i], new MCvScalar(0, 255, 0), 2);
                        }


                        Point[] pointCheters = new Point[numPoints];

                        // 计算圆心到圆周之间中点上的点
                        for (int i = 0; i < numPoints; i++)
                        {
                            //// 计算两点的中点位置 最外圆到圆心 
                            //Point midpoint = new Point((crossCenter.X + pt.X) / 2, (crossCenter.Y + pt.Y) / 2);

                            // 计算两点的中点位置 最外圆到内圆 
                            double angle = (i++) * 2 * Math.PI / numPoints;
                            Point midpoint = new Point(((int)(circle.Center.X + circle.Radius * Math.Cos(angle)) + points[i].X) / 2, ((int)(circle.Center.Y + circle.Radius * Math.Sin(angle)) + points[i].Y) / 2);
                            pointCheters[i] = midpoint;
                        }

                        var tempCC = 0.0d;
                        var tempId = 0;

                        var count = points.Length;
                        for (var i = 0; i < count; i++)
                        {
                            // 360的起始位子标记
                            //if (i == 0)
                            //    CvInvoke.Line(image, new Point((int)circle.Center.X, (int)circle.Center.Y), points[i], new MCvScalar(0, 255, 0), 2);

                            var joinCount   = 0;
                            var joinCc      = 0.0d;

                            joinCc += CalculateColorDifference(GetPixelColor(image, pointCheters[i].X, pointCheters[i].Y), ColorCheck);
                            joinCount++;

                            if (i > 1)
                            {
                                joinCc += CalculateColorDifference(GetPixelColor(image, pointCheters[i - 1].X, pointCheters[i - 1].Y), ColorCheck);
                                joinCount++;
                            }
                            if (i > 2)
                            {
                                joinCc += CalculateColorDifference(GetPixelColor(image, pointCheters[i - 2].X, pointCheters[i - 2].Y), ColorCheck);
                                joinCount++;
                            }

                            if (i < (count - 1 - 1))
                            {
                                joinCc += CalculateColorDifference(GetPixelColor(image, pointCheters[i + 1].X, pointCheters[i + 1].Y), ColorCheck);
                                joinCount++;
                            }

                            if (i < (count - 1 - 2))
                            {
                                joinCc += CalculateColorDifference(GetPixelColor(image, pointCheters[i + 2].X, pointCheters[i + 2].Y), ColorCheck);
                                joinCount++;
                            }

                            joinCc = joinCc / joinCount;

                            if (i == 0)
                            {
                                tempCC = joinCc;
                                tempId = i;
                            }
                            else
                            {
                                if (joinCc < tempCC)
                                {
                                    tempCC = joinCc;
                                    tempId = i;
                                }
                            }
                        }

                        // 360° 起始位从3点开始需要 -90°
                        var outValue = (((double)tempId / (double)numPoints) * 10.0 + 2.5d) ;
                        var outValue2= Math.Round(outValue, MidpointRounding.AwayFromZero) % 10;

                        Console.WriteLine($"Midpoint Color - cc:{tempCC} tempId:{tempId} numPoints:{numPoints} outValue:{outValue} outValue2:{outValue2}");
                        CvInvoke.Line(image,new Point((int)circle.Center.X, (int)circle.Center.Y), points[tempId], new MCvScalar(0, 255, 0), 2);
                    }
                    #endregion
                }
            }

            // 显示结果
            CvInvoke.Imshow("Detected Circles", image);
            CvInvoke.WaitKey(0);
        }


        // 计算圆心附近像素的平均颜色
        static Bgr CalculateAverageColor(Mat image, int centerX, int centerY, int radius)
        {
            Bgr averageColor = new Bgr();

            // 提取圆心附近区域的子图像
            Rectangle roi = new Rectangle(centerX - radius, centerY - radius, 2 * radius, 2 * radius);
            Mat roiImage = new Mat(image, roi);

            // 计算子图像的平均颜色
            MCvScalar scalar = CvInvoke.Mean(roiImage);
            averageColor.Blue = scalar.V0;
            averageColor.Green = scalar.V1;
            averageColor.Red = scalar.V2;

            return averageColor;
        }

        // 获取指定像素位置的颜色
        static Bgr GetPixelColor(Mat image, int x, int y)
        {
            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
            Image<Bgr, byte> img = new Image<Bgr, byte>(image);
            if (rect.Contains(new Point(x, y)))
            {
                return img[y, x];
            }
            return new Bgr(0, 0, 0);
        }

        // 计算两个颜色之间的差异（欧氏距离）
        static double CalculateColorDifference(Bgr color1, Bgr color2)
        {
            double difference = Math.Sqrt(Math.Pow((color2.Blue - color1.Blue), 2) +
                                           Math.Pow((color2.Green - color1.Green), 2) +
                                           Math.Pow((color2.Red - color1.Red), 2));
            return difference;
        }
    }
}
